//获取窗口宽度
if (window.innerWidth)
  winWidth = window.innerWidth;
else if ((document.body) && (document.body.clientWidth))
  winWidth = document.body.clientWidth;
//获取窗口高度
if (window.innerHeight)
  winHeight = window.innerHeight;
else if ((document.body) && (document.body.clientHeight))
  winHeight = document.body.clientHeight;
//通过深入Document内部对body进行检测，获取窗口大小
if (document.documentElement && document.documentElement.clientHeight && document.documentElement.clientWidth) {
  winHeight = document.documentElement.clientHeight;
  winWidth = document.documentElement.clientWidth;
}
var searchstr = "";

var svg = d3.select("svg"),
  width = +svg.attr("width"),
  height = +svg.attr("height");
window.scrollTo((width - winWidth) / 2, (height - winHeight) / 2);

var simulation = d3.forceSimulation()
  .force("link", d3.forceLink().id(function (d) { return d.id; }).distance(50))
  .force("charge", d3.forceManyBody().strength(-150))
  .force("x", d3.forceX(width / 2))
  .force("y", d3.forceY(height / 2));

d3.json("graph.json", function (error, graph) {
  if (error) throw error;
  //绑定相连节点
  for (var i = 0; i < graph.nodes.length; i++) {
    for (var j = 0; j < graph.links.length; j++) {
      if (graph.nodes[i].id == graph.links[j].source) {
        graph.nodes[i][graph.links[j].target] = { id: graph.links[j].target };
      }
      if (graph.nodes[i].id == graph.links[j].target) {
        graph.nodes[i][graph.links[j].source] = { id: graph.links[j].source };
      }
    }
  }

  svg.append("defs").selectAll("marker")
    .data(graph.nodes)
    .enter().append("marker")
    .attr("id", d => `arrow-${d.id}`)
    .attr("viewBox", "0 -5 10 10")
    .attr("refX", d => d.radius + 20)
    .attr("refY", 0)
    .attr("markerWidth", 6)
    .attr("markerHeight", 6)
    .attr("orient", "auto")
    .append("path")
    .attr("fill", "gray")
    .attr("d", "M0,-5L10,0L0,5");

  var link = svg.append("g")
    .attr("class", "links")
    .selectAll("line")
    .data(graph.links)
    .enter().append("line")
    .attr("stroke", "gray")
    .attr("stroke-width", 1)
    .attr("stroke-dasharray", function (d) { return (d.type == "Inheritation") ? "5 3" : "5 0"; })
    .attr("marker-end", d => `url(${new URL(`#arrow-${d.target}`, location)})`);

  var node = svg.append("g")
    .attr("class", "nodes")
    .selectAll("circle")
    .data(graph.nodes)
    .enter().append("circle")
    .attr("fill", function (d) { return d.isInterface ? "#fff" : d3.interpolateRainbow(d.group / graph.groups); })
    .attr("stroke", function (d) { return d3.interpolateRainbow(d.group / graph.groups); })
    .attr("stroke-width", 5)
    .attr("r", function (d) { return d.radius })
    .on("mouseover", function (d, i) {
      //其它节点亮度调低
      node.style("opacity", function (edge) {
        var v = d.id;
        if (edge.id == v || (edge[v] != undefined && edge[v].id == v)) {
          return 1;
        } else {
          return 0.2;
        }
      })
      //其他连先亮度调低
      link.style("opacity", function (edge) {
        if (edge.source.id == d.id || edge.target.id == d.id) {
          return 1;
        } else {
          return 0;
        }
      })
    })
    .on("mouseout", function (d, i) {

      link.style("opacity", function (edge) {
        if (searchstr == "") {
          return 1;
        } else {
          return 0;
        }
      });
      node.style("opacity", function (edge) {
        if (searchstr == "" || edge.id.search(searchstr) != -1) {
          return 1;
        } else {
          return 0.2;
        }
      });

    })
    .call(d3.drag()
      .on("start", dragstarted)
      .on("drag", dragged)
      .on("end", dragended));

  node.append("title")
    .text(function (d) { return d.id; });

  simulation
    .nodes(graph.nodes)
    .on("tick", ticked);

  simulation.force("link")
    .links(graph.links);


  function ticked() {
    link
      .attr("x1", function (d) { return d.source.x; })
      .attr("y1", function (d) { return d.source.y; })
      .attr("x2", function (d) { return d.target.x; })
      .attr("y2", function (d) { return d.target.y; });

    node
      .attr("cx", function (d) { return d.x; })
      .attr("cy", function (d) { return d.y; });
  }
    var searchbar = d3.select("input");
    searchbar.on("change", function (d) {
    searchstr = this.value;
    node.style("opacity", function (edge) {
      if (searchstr == "" || edge.id.search(searchstr) != -1) {
        return 1;
      } else {
        return 0.2;
      }
    });
    link.style("opacity", function (edge) {
      if (searchstr == "") {
        return 1;
      } else {
        return 0;
      }
    });

  });
});

function dragstarted(d) {
  if (!d3.event.active) simulation.alphaTarget(0.3).restart();
  d.fx = d.x;
  d.fy = d.y;
}

function dragged(d) {
  d.fx = d3.event.x;
  d.fy = d3.event.y;
}

function dragended(d) {
  if (!d3.event.active) simulation.alphaTarget(0);
  d.fx = null;
  d.fy = null;
}

